/** \file Heap.cc
 * Definitions for the class Heap.
 *
 * (c) Copyright 2003-2006 by Semih Cemiloglu
 * All rights reserved, see COPYRIGHT file for details.
 *
 * $Id: Heap.cc 119 2006-06-21 04:57:25Z semihc $
 *
 *
 */


#include "Heap.hh"
#include <cstdlib>
#include "HeapMgr.hh"
#include "Debug.hh"

using namespace std;
using namespace TC;


TC_IDENT("$Id$");



Heap::~Heap()
{
}


void* Heap::allocate(size_t size)
{
  if(Redefine_Global_New)
    return malloc(size);
  else
    return ::operator new(size);
}


void Heap::deallocate(void* ptr)
{
  if(Redefine_Global_New)
    free(ptr);
  else
    ::operator delete(ptr);
}


void* Heap::newMem(size_t size, MemType_e /*mtype*/)
{
  // Handle 0-byte requests
  if(0==size) 
    size = 1;

  void* memptr = 0;
  try {

    // See "Effective C++ 2nd Ed." Item 8 by Scott Meyers
    while(true) {
      memptr = allocate(size);
      if(memptr)
        break; // Allocation successful

      // Allocation failed, find out what the current
      // error handling function is
      new_handler globalHandler = set_new_handler(0);
      set_new_handler(globalHandler);
      
      if(globalHandler)
        (*globalHandler)();
      else
        throw std::bad_alloc();
      
    } // end while

  }
  catch(std::bad_alloc&) {
    throw;
  }
  catch(...) {
    throw std::bad_alloc();
  }

  return memptr;
}


void Heap::deleteMem(void* ptr, MemType_e /*mtype*/)
{
  // Check for null pointer
  if(!ptr)
    return;

  deallocate(ptr);
}


void Heap::printStats() const
{
}

void Heap::resetStats()
{
}


/*
 * Overloaded versions of new and delete operators
 * operating on Heap of our choice. They should be
 * declared in global scope for strict standard
 * compliance.
 */ 

void* operator new(size_t size, TC::Heap& h)
{
  return h.newMem(size, Heap::e_Scalar);
}

void* operator new[](size_t size, TC::Heap& h)
{
  return h.newMem(size, Heap::e_Array);
}

void operator delete(void *ptr, TC::Heap& h)
{
  h.deleteMem(ptr, Heap::e_Scalar);
}

void operator delete[](void *ptr, TC::Heap& h)
{
  h.deleteMem(ptr, Heap::e_Array);
}

